var type = (function(){
    var types = 'Boolean Number String Function Array Date RegExp Object Error Symbol Map Set'.split(' ');
    var isTypeFn = {};
    types.forEach(t => {
        isTypeFn['is'+t] = function(obj){
            return Object.prototype.toString.call(obj) === '[object ' + t + ']'
        }
    });

    function getType(obj){
        let str = Object.prototype.toString.call(obj).split(' ')[1];
        return str.slice(0, str.length -1);
    }


    // 该函数的性能进化空间 
    // forin 循环 ===> while 循环 
    // 当前该函数只能对array 和 object进行拷贝， 是否可以对其他可遍历数据类型进行拷贝 还可以对map 和 set进行拷贝
    function forEach(array, callback){
        let index = 0, len = array.length;
        while(index < len){
            callback.call(array, array[index], index);
            index++;
        }
        return array;
    }

    // 获取当前对象的构造函数
    function getConstructor(obj){
        let ctrl = obj.constructor;
        return new ctrl();
    }
    var _deepClone = function(obj, map = new WeakMap()){
        const deepTag = ['Map', 'Set', 'Object', 'Array'];
        if(typeof obj === 'object'){
            // console.log(getType(obj));
            let isArray = isTypeFn.isArray(obj);
            let cloneObj = isArray ? [] : {};
            let type = getType(obj);
            // ======== 防止循环引用 Start =========
            if(map.get(obj)){
                return map.get(obj)
            }
            map.set(obj, cloneObj);
            // ======== 防止循环引用 End =========

            // ======== 性能优化点 通过鉴别当前是否为数组 将所有数据整合为数组进行处理 Start =========
            // console.log(obj);
            // let currArr = isArray ? undefined : obj.keys();
            // forEach(currArr || obj, function(item, index){
            //     if(currArr){
            //         key = value;
            //     }
            //     cloneObj[key] = _deepClone(obj[key], map);
            // })
            // ======== 性能优化点 通过鉴别当前是否为数组 将所有数据整合为数组进行处理 End =========

            // ======== 处理 Map Start =========
            if(type === 'Map'){
                cloneObj = getConstructor(obj);
                obj.forEach((item, key) => {
                    cloneObj.set(key, _deepClone(item, map));
                });
                return cloneObj;
            }
            // ======== 处理 Map End =========
            // ======== 处理 Set Start =========
            if(type === 'Set'){
                cloneObj = getConstructor(obj);
                obj.forEach((item) => {
                    cloneObj.add(_deepClone(item, map));
                });
                return cloneObj;
            }
            // ======== 处理 Set End =========



            for (const key in obj) {
                if (obj.hasOwnProperty(key)) {
                    const element = obj[key];
                    if(typeof element === 'object'){
                        cloneObj[key] = _deepClone(element, map);
                    }else{
                        cloneObj[key] = element;
                    }
                }
            }
            return cloneObj
        }else{
            return obj;
        }
    }
    // console.log(isTypeFn);
    return {
        ...isTypeFn,
        deepClone: _deepClone
    }
})()